package GUI.UI
{
    import GUI.UI.Events.UIEvent;
    import GUI.UI.Events.UIScrollEvent;
    
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Rectangle;

    public class UIContainer extends UIEntity
    {
        private var _autoSize:Boolean;
        private var _viewRect:Rectangle;
        
        /**
         * GUIContainer class shows a specific content, framed inside a mask;
         * 
         * This class override all calls to add/remove childs and point them to content;
         */
        public function UIContainer(pBaseSprite:Sprite, pAutoSize:Boolean=false)
        {
            super(pBaseSprite);
            
            _viewRect       = new Rectangle();
            this.scrollRect = _viewRect;
            autoSize        = pAutoSize;
            
            this.addEventListener(Event.ADDED_TO_STAGE, onAddToStage);
        }
        
        public function get scrollX():Number
        {
            var difference:Number = this.contentWidth - this.viewRectWidth;
            
            if(difference <= 0)//to avoid division by 0;
                return 0;
            
            return _viewRect.x / difference;
        }

        /**
         * scrolls the content in the "X" axis;
         *  
         * @param value must be between 0 and 1;
         * 
         */
        public function set scrollX(value:Number):void
        {
            if(value < 0)
                value = 0;
            else if (value > 1)
                value = 1;
            
            var difference:Number = this.contentHeight - this.viewRectHeight;
            
            if(difference > 0)
            {
                _viewRect.x     = difference * value;
                this.scrollRect = _viewRect;
            }
        }

        public function get scrollY():Number
        {
            var difference:Number = this.contentHeight - this.viewRectHeight;
            
            if(difference <= 0)//to avoid division by 0;
                return 0;
            
            return _viewRect.y / difference;
        }

        /**
         * scrolls the content in the "Y" axis;
         *  
         * @param value must be between 0 and 1;
         * 
         */
        public function set scrollY(value:Number):void
        {
            if(value < 0)
                value = 0;
            else if (value > 1)
                value = 1;
            
            var difference:Number = this.contentHeight - this.viewRectHeight;
            
            if(difference > 0)
            {
                _viewRect.y     = difference * value;
                this.scrollRect = _viewRect;
            }
        }
        
        public function set viewRectWidth(value:Number):void
        {
            _viewRect.width = value;
            this.scrollRect = _viewRect;
        }

        public function get viewRectWidth():Number
        {
            return this._viewRect.width;
        }

        public function set viewRectHeight(value:Number):void
        {
            _viewRect.height = value;
            this.scrollRect  = _viewRect;
        }

        public function get viewRectHeight():Number
        {
            return _viewRect.height;
        }
        
        /**
         * Once the content is added to stage, the scrollRect property will crop his size. 
         * Because of this, once added we will use the transform property.
         *  
         * @return the content width;
         */
        public function get contentWidth():Number
        {
            if(this.stage)//if already added to stage
                return this.transform.pixelBounds.width;
            else
                return this.width;
        }

        /**
         * Once the content is added to stage, the scrollRect property will crop his size. 
         * Because of this, once added we will use the transform property.
         *  
         * @return the content height;
         */
        public function get contentHeight():Number
        {
            if(this.stage)//if already added to stage
                return this.transform.pixelBounds.height;
            else
                return this.height;
        }
        
        public override function destroy():void
        {   
            _viewRect = null;

            unRegisterRenderEvent();

            this.removeEventListener(Event.ADDED_TO_STAGE, onAddToStage);
            
            super.destroy();
        }
        
        public override function processUIEvent(e:UIEvent):void
        {
            var event:UIScrollEvent;
            
            switch (e.type)
            {
                case UIScrollEvent.SCROLL_MORE:
                    event = e as UIScrollEvent;
                    
                    if(event.vertical)
                        this.scrollY --;
                    else
                        this.scrollX ++;
                break;
                
                case UIScrollEvent.SCROLL_LESS:
                    event = e as UIScrollEvent;
                    
                    if(event.vertical)
                        this.scrollY ++;
                    else
                        this.scrollX --;
                break;
            }
        }

        /**
         * the autoSize property will adjust the viewRect to the object size automaticaly;
         */
        public function get autoSize():Boolean
        {
            return _autoSize;
        }

        public function set autoSize(value:Boolean):void
        {   
            _autoSize = value;
            
            if(!value)
                unRegisterRenderEvent();
        }
        
        public override function set width(value:Number):void
        {
            if(_autoSize)
                registerRenderEvent();
            
            super.width = value;
        }

        public override function set height(value:Number):void
        {
            if(_autoSize)
                registerRenderEvent();
            
            super.height = value;
        }
        
        public override function set scaleX(value:Number):void
        {
            if(_autoSize)
                registerRenderEvent();
            
            super.width = value;
        }

        public override function set scaleY(value:Number):void
        {
            if(_autoSize)
                registerRenderEvent();
            
            super.height = value;
        }
        
        public override function get graphics():Graphics
        {
            if(_autoSize)
                registerRenderEvent();
            
            return super.graphics;
        }
        
        protected function registerRenderEvent():void
        {
            if(stage && !hasEventListener(Event.RENDER))
            {
                stage.invalidate();
                this.addEventListener(Event.RENDER, onRender);
            }
        }
        
        protected function unRegisterRenderEvent():void
        {
            if(hasEventListener(Event.RENDER))
                this.removeEventListener(Event.RENDER, onRender);
        }
        
        protected function onRender(e:Event):void
        {
            this.viewRectWidth  = this.contentWidth;
            this.viewRectHeight = this.contentHeight;
            
            unRegisterRenderEvent();
        }
        
        protected function onAddToStage(e:Event):void
        {
            //on added to stage, check if we have a Render Event pending to register;
            if(autoSize)
                registerRenderEvent();
        }
    }
}